package com.lxb.myforum.service

import java.util.*
import java.util.stream.Collectors

import com.lxb.myforum.base.BaseService
import com.lxb.myforum.domain.ResResult
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate
import org.springframework.stereotype.Service

import com.lxb.myforum.pojo.Authority
import com.lxb.myforum.pojo.Role
import com.lxb.myforum.repository.AuthorityRepository
import com.lxb.myforum.repository.RoleRepository

/**
 *
 * @author lxb
 */
@Service
class RoleService @Autowired constructor(
        private val roleRepository: RoleRepository,
        private val authorityRepository: AuthorityRepository,
        private val namedParameterJdbcTemplate: NamedParameterJdbcTemplate
) : BaseService() {

    /**
     * 获取Role 信息列表
     * @param pageable 分页信息
     * @return 分页结果
     */
    fun getRoles(pageable: Pageable): Page<Role> {
        return roleRepository.findAll(pageable)
    }

    /**
     * 新增或者更新数据
     * @param role 要保存的Role
     * @return [Role]
     */
    fun save(role: Role): Role = roleRepository.save(role)

    /**
     * 根据id删除对应的Role
     * @param id
     * @return
     */
    fun deleteRoleById(id: Long): ResResult {
        val rr = ResResult("delete")

        // 只会删除该id的Resource和与该Resource相关的联系（如果是多对多，即是第三张表的数据【两者之间的联系】）
        // 并不会删除与该Resource相关连的表的信息
        try {
            roleRepository.deleteById(id)
            rr.isSuccess = true
        } catch (e: IllegalArgumentException) {
            rr.isSuccess = false
        }

        return rr
    }

    /**
     * 批量删除数据
     * @param ids
     * @return
     */
    fun delRolesByIds(ids: List<Long>): Map<String, Any> {
        val result = HashMap<String, Any>()
        result["action"] = "delete"

        val roles = ids.stream()
                .map<Role> { Role(it) }
                .collect(Collectors.toList())
        try {
            roleRepository.deleteAll(roles)
            result["result"] = 1
        } catch (e: IllegalArgumentException) {
            result["result"] = -1
        }

        return result
    }

    /**
     * 获取ID为 *roleId* 的角色所拥有的权限
     * @param roleId
     */
    fun findOwnAuthorities(roleId: Long): Collection<Authority> {
        return roleRepository.findById(roleId)
                .map<Collection<Authority>> { it.authorities }
                .orElse(null)
    }

    //SELECT * FROM t_authority AS a RIGHT OUTER JOIN t_role_authority AS b ON a.id = b.authority_id WHERE b.role_id != 1;

    /**
     * 获取ID为 *roleId* 的角色所不包含的权限
     * @param roleId
     * @return
     */
    fun findNotOwnAuthorities(roleId: Long): Collection<Authority> {
        // Role role = roleRepository.findOne(roleId);

        return authorityRepository.findNotRoleAuthorities(roleId)
        //		Collection<Authority> authorities =  role.getAuthorities();
        //		List<Authority> authorities2 = authorityRepository.findAll(new Specification<Authority>() {
        //			@Override
        //			public Predicate toPredicate(Root<Authority> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
        //				List<Predicate> predicates = authorities.stream().map(auth -> {
        //					return cb.notEqual(root.get("id"), auth.getId());
        //				}).collect(Collectors.toList());
        //				query.where(predicates.toArray(new Predicate[predicates.size()]));
        //				return null;
        //			}
        //		});
        //		return authorities2;
    }

    /**
     * 为角色删除权限
     * @param roleId
     * @param authIds
     * @return
     */
    fun delRoleAuthorities(roleId: Long, authIds: Set<Long>): MutableMap<String, Any> {
        val result = HashMap<String, Any>()
        val delSql = "delete from t_role_authority where role_id = :roleId and authority_id = :authId"
        try {
            val batchValues = authIds.stream()
                    .map { authId ->
                        val mapSqlParameterSource = MapSqlParameterSource("authId", authId)
                        mapSqlParameterSource.addValue("roleId", roleId)
                        mapSqlParameterSource
                    }
                    .toArray<MapSqlParameterSource> { arrayOfNulls(it) }
            namedParameterJdbcTemplate.batchUpdate(delSql, batchValues)

            result["result"] = 1
            result["msg"] = "删除成功"
        } catch (e: Exception) {
            result["result"] = -1
            result["msg"] = "删除失败"
        }

        return result
    }

    /**
     * 为角色添加权限
     * @param roleId
     * @param authIds
     * @return
     */
    fun addRoleAuthorities(roleId: Long, authIds: Set<Long>): MutableMap<String, Any> {
        val result = HashMap<String, Any>()
        val insertSql = "insert into t_role_authority(role_id, authority_id) values(:roleId, :authId)"
        try {
            val batchValues = authIds.stream()
                    .map { authId ->
                        val mapSqlParameterSource = MapSqlParameterSource("authId", authId)
                        mapSqlParameterSource.addValue("roleId", roleId)
                        mapSqlParameterSource
                    }
                    .toArray<MapSqlParameterSource> { arrayOfNulls(it) }
            namedParameterJdbcTemplate.batchUpdate(insertSql, batchValues)

            result["result"] = 1
            result["msg"] = "添加成功"
        } catch (e: Exception) {
            result["result"] = -1
            result["msg"] = "添加失败"
        }

        return result
    }
}
